// Go作者版权所有。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

package types

import (
	"cmd/compile/internal/base"
	"cmd/internal/src"
	"fmt"
	"sync"
)

// 对象表示ir.Node，但不需要导入cmd/compile/internal/ir，
// 这将导致一个导入周期。在其他包中的使用必须为assert类型
// 对象类型的值到ir.Node或更具体的类型。
type Object interface {
	Pos() src.XPos
	Sym() *Sym
	Type() *Type
}

// TypeObject是表示命名类型的对象。
type TypeObject interface {
	Object
	TypeDefn() *Type // 对于“类型T Defn”，返回Defn
}

// VarObject是表示函数参数、变量或结构字段的对象。
type VarObject interface {
	Object
	RecordFrameOffset(int64) // 保存帧偏移
}

// go：生成梯边梁-类型种类-前缀T类型.go

// 种类描述一种类型。
type Kind uint8

const (
	Txxx Kind = iota

	TINT8
	TUINT8
	TINT16
	TUINT16
	TINT32
	TUINT32
	TINT64
	TUINT64
	TINT
	TUINT
	TUINTPTR

	TCOMPLEX64
	TCOMPLEX128

	TFLOAT32
	TFLOAT64

	TBOOL

	TPTR
	TFUNC
	TSLICE
	TARRAY
	TSTRUCT
	TCHAN
	TMAP
	TINTER
	TFORW
	TANY
	TSTRING
	TUNSAFEPTR
	TTYPEPARAM

	// 文字的伪类型
	TIDEAL // 非类型化数值常量
	TNIL
	TBLANK

	// 框架布局的伪类型
	TFUNCARGS
	TCHANARGS

	// SSA后端类型
	TSSA     // SSA后端使用的内部类型（标志、内存等）
	TTUPLE   // SSA后端使用的一对类型
	TRESULTS // 多种类型；调用函数或方法的结果，最后有一个内存。

	NTYPE
)

// ChanDir是指一个频道是否可以发送、接收或两者兼有。
type ChanDir uint8

func (c ChanDir) CanRecv() bool { return c&Crecv != 0 }
func (c ChanDir) CanSend() bool { return c&Csend != 0 }

const (
	// 渠道类型
	// 必须匹配../../../../../reflect/type.go:/ChanDir
	Crecv ChanDir = 1 << 0
	Csend ChanDir = 1 << 1
	Cboth ChanDir = Crecv | Csend
)

// 类型存储指向预先声明的命名类型的指针。
// None
// 它还存储指向几种特殊类型的指针：
// -Types[TANY]是子参数类型识别的占位符“any”类型。
// -类型[tBLUL]表示空白变量的类型。
// -Types[TNIL]表示预先声明的“nil”值的类型。
// -类型[TUNSAFEPTR]是包的指针类型。
var Types [NTYPE]*Type

var (
	// 预先声明的别名类型。保持分离以获得更好的错误消息。
	ByteType *Type
	RuneType *Type

	// 预先声明的错误接口类型。
	ErrorType *Type

	// 表示非类型化字符串和布尔常量的类型。
	UntypedString = New(TSTRING)
	UntypedBool   = New(TBOOL)

	// 表示非类型化数值常量的类型。
	UntypedInt     = New(TIDEAL)
	UntypedRune    = New(TIDEAL)
	UntypedFloat   = New(TIDEAL)
	UntypedComplex = New(TIDEAL)
)

// 类型表示Go类型。
type Type struct {
	// Extra包含额外的特定于etype的字段。
	// 作为优化，这些特定于etype的结构
	// 一个指针形状的字段尽可能存储为值而不是指针。
	// None
	// TMAP:*地图
	// t前进：*前进
	// TFUNC:*Func
	// t结构：*结构
	// 着色剂：*界面
	// tfunargs:FuncArgs
	// TCHANARGS:ChanArgs
	// TCHAN:*陈
	// TPTR:Ptr
	// TARRAY:*阵列
	// 切片
	// TSSA：字符串
	// TTYPEPARAM:*接口（尽管我们可能不需要存储/使用接口信息）
	Extra interface{}

	// Width是此类型的宽度（以字节为单位）。
	Width int64 // 如果对齐>0，则有效

	// 基本方法列表（不包括嵌入）
	methods Fields
	// 所有方法列表（包括嵌入）
	allMethods Fields

	// 命名类型的规范OTYPE节点（应该是具有相同sym的ir.Name节点）
	nod Object
	// 已定义类型的基础类型（文本类型或预声明类型）
	underlying *Type

	// 组合类型的缓存，此类型为元素类型。
	cache struct {
		ptr   *Type // *T、 还是零
		slice *Type // []T或零
	}

	sym    *Sym  // 包含名称的符号，用于命名类型
	Vargen int32 // OTYPE/OnName的唯一名称

	kind  Kind  // 种类
	Align uint8 // 此类型所需的对齐方式，以字节为单位（0表示尚未计算宽度和对齐方式）

	flags bitset8

	// 对于已定义（命名）泛型类型，指向类型参数列表的指针
	// 需要实例化的此类型的（按顺序）。对于
	// 完全实例化的泛型类型，这是用于实例化的TARG
	// 它们（在生成相应的实例化
	// 方法）。rparams仅为泛型或非泛型的命名类型设置
	// 从泛型类型完全实例化，否则设置为nil。
	rparams *[]*Type
}

func (*Type) CanBeAnSSAAux() {}

const (
	typeNotInHeap  = 1 << iota // 无法为堆分配类型
	typeBroke                  // 断开类型定义
	typeNoalg                  // 抑制hash和eq算法生成
	typeDeferwidth             // 宽度计算已延迟，类型位于deferredTypeStack上
	typeRecur
	typeHasTParam // 类型（泛型函数或类型）中的某个位置有一个typeparam
)

func (t *Type) NotInHeap() bool  { return t.flags&typeNotInHeap != 0 }
func (t *Type) Broke() bool      { return t.flags&typeBroke != 0 }
func (t *Type) Noalg() bool      { return t.flags&typeNoalg != 0 }
func (t *Type) Deferwidth() bool { return t.flags&typeDeferwidth != 0 }
func (t *Type) Recur() bool      { return t.flags&typeRecur != 0 }
func (t *Type) HasTParam() bool  { return t.flags&typeHasTParam != 0 }

func (t *Type) SetNotInHeap(b bool)  { t.flags.set(typeNotInHeap, b) }
func (t *Type) SetBroke(b bool)      { t.flags.set(typeBroke, b) }
func (t *Type) SetNoalg(b bool)      { t.flags.set(typeNoalg, b) }
func (t *Type) SetDeferwidth(b bool) { t.flags.set(typeDeferwidth, b) }
func (t *Type) SetRecur(b bool)      { t.flags.set(typeRecur, b) }
func (t *Type) SetHasTParam(b bool)  { t.flags.set(typeHasTParam, b) }

// Kind返回类型t的类型。
func (t *Type) Kind() Kind { return t.kind }

// Sym返回类型t的名称。
func (t *Type) Sym() *Sym       { return t.sym }
func (t *Type) SetSym(sym *Sym) { t.sym = sym }

// 基础返回t类型的基础类型。
func (t *Type) Underlying() *Type { return t.underlying }

// SetNod将t与语法节点n相关联。
func (t *Type) SetNod(n Object) {
	// t、 nod可以是非零
	// 对于共享*类型，如[]字节或接口{}。
	if t.nod == nil {
		t.nod = n
	}
}

// Pos返回与t关联的位置（如果有）。
// 这只能用于诊断。
func (t *Type) Pos() src.XPos {
	if t.nod != nil {
		return t.nod.Pos()
	}
	return src.NoXPos
}

func (t *Type) RParams() []*Type {
	if t.rparams == nil {
		return nil
	}
	return *t.rparams
}

func (t *Type) SetRParams(rparams []*Type) {
	if len(rparams) == 0 {
		base.Fatalf("Setting nil or zero-length rparams")
	}
	t.rparams = &rparams
	if t.HasTParam() {
		return
	}
	// 如果任何rparam是或具有类型param，则应设置HasTParam。这是
	// 处理不引用其任何
	// 类型参数（例如，最常见的是空结构）。
	for _, rparam := range rparams {
		if rparam.HasTParam() {
			t.SetHasTParam(true)
			break
		}
	}
}

// 为清晰起见，NoPkg为零*Pkg值。
// 它用于构造未导出的类型
// 因此不需要与任何包关联。
var NoPkg *Pkg = nil

// Pkg返回t出现在其中的包。
// None
// Pkg仅为函数、结构和接口类型定义
// （即，具有命名元素的类型）。此信息未被用户使用
// cmd/compile本身，但我们需要跟踪它，因为它是由
// go/types API。
func (t *Type) Pkg() *Pkg {
	switch t.kind {
	case TFUNC:
		return t.Extra.(*Func).pkg
	case TSTRUCT:
		return t.Extra.(*Struct).pkg
	case TINTER:
		return t.Extra.(*Interface).pkg
	default:
		base.Fatalf("Pkg: unexpected kind: %v", t)
		return nil
	}
}

// 映射包含特定于映射的类型字段。
type Map struct {
	Key  *Type // 键类型
	Elem *Type // Val（elem）型

	Bucket *Type // 表示哈希桶的内部结构类型
	Hmap   *Type // 表示Hmap的内部结构类型（映射头对象）
	Hiter  *Type // 表示哈希迭代器状态的内部结构类型
}

// MapType返回t的额外映射特定字段。
func (t *Type) MapType() *Map {
	t.wantEtype(TMAP)
	return t.Extra.(*Map)
}

// 转发包含特定于转发类型的类型字段。
type Forward struct {
	Copyto      []*Type  // 将最终值复制到何处
	Embedlineno src.XPos // 首次将此类型用作嵌入类型
}

// ForwardType返回t的额外转发类型特定字段。
func (t *Type) ForwardType() *Forward {
	t.wantEtype(TFORW)
	return t.Extra.(*Forward)
}

// Func包含特定于Func类型的类型字段。
type Func struct {
	Receiver *Type // 函数接收器
	Results  *Type // 功能结果
	Params   *Type // 函数参数
	TParams  *Type // 接收器（if方法）或函数的类型参数

	pkg *Pkg

	// Argwid是函数接收器、参数和结果的总宽度。
	// 它通过临时TFUNCARGS类型进行计算。
	// 请注意，TFUNC的宽度是Widthptr。
	Argwid int64
}

// FuncType返回t的额外func特定字段。
func (t *Type) FuncType() *Func {
	t.wantEtype(TFUNC)
	return t.Extra.(*Func)
}

// StructType包含特定于结构类型的类型字段。
type Struct struct {
	fields Fields
	pkg    *Pkg

	// 映射有三个关联的内部结构（请参见结构映射类型）。
	// 映射将此类结构链接回其映射类型。
	Map *Type

	Funarg Funarg // arg struct的函数参数类型
}

// Fnstruct记录函数参数的类型
type Funarg uint8

const (
	FunargNone    Funarg = iota
	FunargRcvr           // 接受者
	FunargParams         // 输入参数
	FunargResults        // 输出结果
	FunargTparams        // 类型参数
)

// StructType返回t的额外结构特定字段。
func (t *Type) StructType() *Struct {
	t.wantEtype(TSTRUCT)
	return t.Extra.(*Struct)
}

// 接口包含特定于接口类型的类型字段。
type Interface struct {
	pkg *Pkg
}

// Ptr包含特定于指针类型的类型字段。
type Ptr struct {
	Elem *Type // 元素类型
}

// ChanArgs包含特定于TCHANARGS类型的类型字段。
type ChanArgs struct {
	T *Type // 对其元素需要进行宽度检查的chan类型的引用
}

// None
type FuncArgs struct {
	T *Type // 对其元素需要进行宽度检查的func类型的引用
}

// Chan包含特定于通道类型的类型字段。
type Chan struct {
	Elem *Type   // 元素类型
	Dir  ChanDir // 通道方向
}

// ChanType返回t的额外通道特定字段。
func (t *Type) ChanType() *Chan {
	t.wantEtype(TCHAN)
	return t.Extra.(*Chan)
}

type Tuple struct {
	first  *Type
	second *Type
	// 任何具有内存类型的元组都必须将该内存类型放在第二位。
}

// 结果是将延迟展开的调用的输出。
type Results struct {
	Types []*Type // 最后一个元素是调用的内存输出。
}

// 数组包含特定于数组类型的类型字段。
type Array struct {
	Elem  *Type // 元素类型
	Bound int64 // 元素数量<如果未知，则返回0
}

// 切片包含特定于切片类型的类型字段。
type Slice struct {
	Elem *Type // 元素类型
}

// 字段是一个（符号，类型）配对以及一些其他信息，
// 根据上下文，用于表示：
// -结构中的字段
// -接口中的方法或与命名类型关联的方法
// -函数参数
type Field struct {
	flags bitset8

	Embedded uint8 // 嵌入字段

	Pos  src.XPos
	Sym  *Sym
	Type *Type  // 字段类型
	Note string // 文字字符串注释

	// 对于表示函数参数的字段，Nname点
	// 到关联的ONAME节点。
	Nname Object

	// 此字段或方法在其封闭结构中的偏移量（字节）
	// 或接口类型。例外情况：如果字段为函数接收器，则为arg或
	// 结果，那么这就是伪FUNARG偏移量；类型不知道Abi。
	Offset int64
}

const (
	fieldIsDDD = 1 << iota // 字段是。。。论点
	fieldBroke             // 断开字段定义
	fieldNointerface
)

func (f *Field) IsDDD() bool       { return f.flags&fieldIsDDD != 0 }
func (f *Field) Broke() bool       { return f.flags&fieldBroke != 0 }
func (f *Field) Nointerface() bool { return f.flags&fieldNointerface != 0 }

func (f *Field) SetIsDDD(b bool)       { f.flags.set(fieldIsDDD, b) }
func (f *Field) SetBroke(b bool)       { f.flags.set(fieldBroke, b) }
func (f *Field) SetNointerface(b bool) { f.flags.set(fieldNointerface, b) }

// End返回此字段后面第一个字节的偏移量。
func (f *Field) End() int64 {
	return f.Offset + f.Type.Width
}

// IsMethod报告f是否表示方法而不是结构字段。
func (f *Field) IsMethod() bool {
	return f.Type.kind == TFUNC && f.Type.Recv() != nil
}

// 字段是指向*字段切片的指针。
// 这样可以在没有字段或方法的类型中节省空间
// 与*字段的简单切片相比。
type Fields struct {
	s *[]*Field
}

// Len返回f中的条目数。
func (f *Fields) Len() int {
	if f.s == nil {
		return 0
	}
	return len(*f.s)
}

// Slice以Slice的形式返回f中的条目。
// 切片条目的更改将反映在f中。
func (f *Fields) Slice() []*Field {
	if f.s == nil {
		return nil
	}
	return *f.s
}

// 索引返回字段的第i个元素。
// 如果f至少没有i+1元素，它就会恐慌。
func (f *Fields) Index(i int) *Field {
	return (*f.s)[i]
}

// 将f设置为一个切片。
// 这将获得切片的所有权。
func (f *Fields) Set(s []*Field) {
	if len(s) == 0 {
		f.s = nil
	} else {
		// 复制s并获取t而不是s的地址以避免
		// len（s）==0的情况下的分配。
		t := s
		f.s = &t
	}
}

// 将条目追加到f。
func (f *Fields) Append(s ...*Field) {
	if f.s == nil {
		f.s = new([]*Field)
	}
	*f.s = append(*f.s, s...)
}

// New返回指定类型的新类型。
func New(et Kind) *Type {
	t := &Type{
		kind:  et,
		Width: BADWIDTH,
	}
	t.underlying = t
	// 托多（约书亚）：懒洋洋地初始化其中一些？
	switch t.kind {
	case TMAP:
		t.Extra = new(Map)
	case TFORW:
		t.Extra = new(Forward)
	case TFUNC:
		t.Extra = new(Func)
	case TSTRUCT:
		t.Extra = new(Struct)
	case TINTER:
		t.Extra = new(Interface)
	case TPTR:
		t.Extra = Ptr{}
	case TCHANARGS:
		t.Extra = ChanArgs{}
	case TFUNCARGS:
		t.Extra = FuncArgs{}
	case TCHAN:
		t.Extra = new(Chan)
	case TTUPLE:
		t.Extra = new(Tuple)
	case TRESULTS:
		t.Extra = new(Results)
	case TTYPEPARAM:
		t.Extra = new(Interface)
	}
	return t
}

// NewArray返回新的固定长度数组类型。
func NewArray(elem *Type, bound int64) *Type {
	if bound < 0 {
		base.Fatalf("NewArray: invalid bound %v", bound)
	}
	t := New(TARRAY)
	t.Extra = &Array{Elem: elem, Bound: bound}
	t.SetNotInHeap(elem.NotInHeap())
	if elem.HasTParam() {
		t.SetHasTParam(true)
	}
	return t
}

// NewSlice返回元素类型为elem的切片类型。
func NewSlice(elem *Type) *Type {
	if t := elem.cache.slice; t != nil {
		if t.Elem() != elem {
			base.Fatalf("elem mismatch")
		}
		return t
	}

	t := New(TSLICE)
	t.Extra = Slice{Elem: elem}
	elem.cache.slice = t
	if elem.HasTParam() {
		t.SetHasTParam(true)
	}
	return t
}

// NewChan返回一个带有方向dir的新chan类型。
func NewChan(elem *Type, dir ChanDir) *Type {
	t := New(TCHAN)
	ct := t.ChanType()
	ct.Elem = elem
	ct.Dir = dir
	if elem.HasTParam() {
		t.SetHasTParam(true)
	}
	return t
}

func NewTuple(t1, t2 *Type) *Type {
	t := New(TTUPLE)
	t.Extra.(*Tuple).first = t1
	t.Extra.(*Tuple).second = t2
	if t1.HasTParam() || t2.HasTParam() {
		t.SetHasTParam(true)
	}
	return t
}

func newResults(types []*Type) *Type {
	t := New(TRESULTS)
	t.Extra.(*Results).Types = types
	return t
}

func NewResults(types []*Type) *Type {
	if len(types) == 1 && types[0] == TypeMem {
		return TypeResultMem
	}
	return newResults(types)
}

func newSSA(name string) *Type {
	t := New(TSSA)
	t.Extra = name
	return t
}

// NewMap返回一个键类型为k、元素（aka值）类型为v的新映射类型。
func NewMap(k, v *Type) *Type {
	t := New(TMAP)
	mt := t.MapType()
	mt.Key = k
	mt.Elem = v
	if k.HasTParam() || v.HasTParam() {
		t.SetHasTParam(true)
	}
	return t
}

// newptrcachenabled控制是否将*T类型缓存在T中。
// 缓存在启动后端之前被禁用。
// 这允许后端并行运行。
var NewPtrCacheEnabled = true

// NewPtr返回指向t的指针类型。
func NewPtr(elem *Type) *Type {
	if elem == nil {
		base.Fatalf("NewPtr: pointer to elem Type is nil")
	}

	if t := elem.cache.ptr; t != nil {
		if t.Elem() != elem {
			base.Fatalf("NewPtr: elem mismatch")
		}
		if elem.HasTParam() {
			// 重复使用缓存时的额外检查，因为元素
			// 可能尚未确定（即TFORW类型）
			// 当缓存此条目时。
			t.SetHasTParam(true)
		}
		return t
	}

	t := New(TPTR)
	t.Extra = Ptr{Elem: elem}
	t.Width = int64(PtrSize)
	t.Align = uint8(PtrSize)
	if NewPtrCacheEnabled {
		elem.cache.ptr = t
	}
	if elem.HasTParam() {
		t.SetHasTParam(true)
	}
	return t
}

// NewChanArgs为通道类型c返回新的TCHANARGS类型。
func NewChanArgs(c *Type) *Type {
	t := New(TCHANARGS)
	t.Extra = ChanArgs{T: c}
	return t
}

// NewFuncArgs为func类型f返回一个新的TFUNCARGS类型。
func NewFuncArgs(f *Type) *Type {
	t := New(TFUNCARGS)
	t.Extra = FuncArgs{T: f}
	return t
}

func NewField(pos src.XPos, sym *Sym, typ *Type) *Field {
	f := &Field{
		Pos:    pos,
		Sym:    sym,
		Type:   typ,
		Offset: BADWIDTH,
	}
	if typ == nil {
		f.SetBroke(true)
	}
	return f
}

// 将“any”的实例替换为连续的
// 从类型中删除的元素。它返回被替换的类型。
func SubstAny(t *Type, types *[]*Type) *Type {
	if t == nil {
		return nil
	}

	switch t.kind {
	default:
		// 保持类型不变。

	case TANY:
		if len(*types) == 0 {
			base.Fatalf("SubstArgTypes: not enough argument types")
		}
		t = (*types)[0]
		*types = (*types)[1:]

	case TPTR:
		elem := SubstAny(t.Elem(), types)
		if elem != t.Elem() {
			t = t.copy()
			t.Extra = Ptr{Elem: elem}
		}

	case TARRAY:
		elem := SubstAny(t.Elem(), types)
		if elem != t.Elem() {
			t = t.copy()
			t.Extra.(*Array).Elem = elem
		}

	case TSLICE:
		elem := SubstAny(t.Elem(), types)
		if elem != t.Elem() {
			t = t.copy()
			t.Extra = Slice{Elem: elem}
		}

	case TCHAN:
		elem := SubstAny(t.Elem(), types)
		if elem != t.Elem() {
			t = t.copy()
			t.Extra.(*Chan).Elem = elem
		}

	case TMAP:
		key := SubstAny(t.Key(), types)
		elem := SubstAny(t.Elem(), types)
		if key != t.Key() || elem != t.Elem() {
			t = t.copy()
			t.Extra.(*Map).Key = key
			t.Extra.(*Map).Elem = elem
		}

	case TFUNC:
		recvs := SubstAny(t.Recvs(), types)
		params := SubstAny(t.Params(), types)
		results := SubstAny(t.Results(), types)
		if recvs != t.Recvs() || params != t.Params() || results != t.Results() {
			t = t.copy()
			t.FuncType().Receiver = recvs
			t.FuncType().Results = results
			t.FuncType().Params = params
		}

	case TSTRUCT:
		// 复制所有字段，包括类型不变的字段。
		// 这可以防止函数之间出现别名，这可能导致以后的错误
		// 字段的偏移量被错误地覆盖。
		fields := t.FieldSlice()
		nfs := make([]*Field, len(fields))
		for i, f := range fields {
			nft := SubstAny(f.Type, types)
			nfs[i] = f.Copy()
			nfs[i].Type = nft
		}
		t = t.copy()
		t.SetFields(nfs)
	}

	return t
}

// copy返回类型的浅层副本。
func (t *Type) copy() *Type {
	if t == nil {
		return nil
	}
	nt := *t
	// 复制任何*T额外字段，以避免别名
	switch t.kind {
	case TMAP:
		x := *t.Extra.(*Map)
		nt.Extra = &x
	case TFORW:
		x := *t.Extra.(*Forward)
		nt.Extra = &x
	case TFUNC:
		x := *t.Extra.(*Func)
		nt.Extra = &x
	case TSTRUCT:
		x := *t.Extra.(*Struct)
		nt.Extra = &x
	case TINTER:
		x := *t.Extra.(*Interface)
		nt.Extra = &x
	case TCHAN:
		x := *t.Extra.(*Chan)
		nt.Extra = &x
	case TARRAY:
		x := *t.Extra.(*Array)
		nt.Extra = &x
	case TTUPLE, TSSA, TRESULTS:
		base.Fatalf("ssa types cannot be copied")
	}
	// TODO（mdempsky）：找出为什么这是必要的并解释。
	if t.underlying == t {
		nt.underlying = &nt
	}
	return &nt
}

func (f *Field) Copy() *Field {
	nf := *f
	return &nf
}

func (t *Type) wantEtype(et Kind) {
	if t.kind != et {
		base.Fatalf("want %v, but have %v", et, t)
	}
}

func (t *Type) Recvs() *Type   { return t.FuncType().Receiver }
func (t *Type) TParams() *Type { return t.FuncType().TParams }
func (t *Type) Params() *Type  { return t.FuncType().Params }
func (t *Type) Results() *Type { return t.FuncType().Results }

func (t *Type) NumRecvs() int   { return t.FuncType().Receiver.NumFields() }
func (t *Type) NumTParams() int { return t.FuncType().TParams.NumFields() }
func (t *Type) NumParams() int  { return t.FuncType().Params.NumFields() }
func (t *Type) NumResults() int { return t.FuncType().Results.NumFields() }

// IsVariadic报告函数类型t是否是可变的。
func (t *Type) IsVariadic() bool {
	n := t.NumParams()
	return n > 0 && t.Params().Field(n-1).IsDDD()
}

// Recv返回函数类型为t的接收器（如果有）。
func (t *Type) Recv() *Field {
	s := t.Recvs()
	if s.NumFields() == 0 {
		return nil
	}
	return s.Field(0)
}

// RecvsParamsResults存储函数类型的访问器函数
// 接收器、参数和结果参数的顺序。
// 它可以用于迭代函数的所有参数列表。
var RecvsParamsResults = [3]func(*Type) *Type{
	(*Type).Recvs, (*Type).Params, (*Type).Results,
}

// RecvsParams类似于RecvsParamsResults，但省略了结果参数。
var RecvsParams = [2]func(*Type) *Type{
	(*Type).Recvs, (*Type).Params,
}

// ParamsResults与RecvsParamsResults类似，但省略了接收器参数。
var ParamsResults = [2]func(*Type) *Type{
	(*Type).Params, (*Type).Results,
}

// Key返回映射类型t的键类型。
func (t *Type) Key() *Type {
	t.wantEtype(TMAP)
	return t.Extra.(*Map).Key
}

// Elem返回t的元素类型。
// 可用于指针、通道、数组、切片和贴图。
func (t *Type) Elem() *Type {
	switch t.kind {
	case TPTR:
		return t.Extra.(Ptr).Elem
	case TARRAY:
		return t.Extra.(*Array).Elem
	case TSLICE:
		return t.Extra.(Slice).Elem
	case TCHAN:
		return t.Extra.(*Chan).Elem
	case TMAP:
		return t.Extra.(*Map).Elem
	}
	base.Fatalf("Type.Elem %s", t.kind)
	return nil
}

// ChanArgs返回TCHANARGS类型t的通道类型。
func (t *Type) ChanArgs() *Type {
	t.wantEtype(TCHANARGS)
	return t.Extra.(ChanArgs).T
}

// FuncArgs返回tfunargs类型t的func类型。
func (t *Type) FuncArgs() *Type {
	t.wantEtype(TFUNCARGS)
	return t.Extra.(FuncArgs).T
}

// IsFuncArgStruct报告t是否是表示函数参数的结构。
func (t *Type) IsFuncArgStruct() bool {
	return t.kind == TSTRUCT && t.Extra.(*Struct).Funarg != FunargNone
}

// 方法返回指向类型t的基方法（不包括嵌入）的指针。
// 这些可以是具体的方法（对于非接口类型）或接口
// 方法（用于接口类型）。
func (t *Type) Methods() *Fields {
	return &t.methods
}

// AllMethods返回指向t类型的所有方法（包括嵌入）的指针。
// 对于接口类型，这是一组通常迭代的方法。
func (t *Type) AllMethods() *Fields {
	if t.kind == TINTER {
		// 动态计算接口类型的完整方法集
		// 现在，如果还没有完成的话。
		CalcSize(t)
	}
	return &t.allMethods
}

// SetAllMethods为类型t设置所有方法（包括嵌入）的集合。
// 使用此方法而不是t.AllMethods（）.Set（），后者可能会在上调用CalcSize（）
// 未初始化的接口类型。
func (t *Type) SetAllMethods(fs []*Field) {
	t.allMethods.Set(fs)
}

// Fields返回结构类型为t的字段。
func (t *Type) Fields() *Fields {
	t.wantEtype(TSTRUCT)
	return &t.Extra.(*Struct).fields
}

// 字段返回结构类型为t的第i个字段。
func (t *Type) Field(i int) *Field {
	return t.Fields().Slice()[i]
}

// FieldSlice返回包含的所有字段的
// 结构类型t。
func (t *Type) FieldSlice() []*Field {
	return t.Fields().Slice()
}

// SetFields将结构类型t的字段设置为字段。
func (t *Type) SetFields(fields []*Field) {
	// 如果我们以前计算过t的宽度，
	// 然后是其他类型，例如函数签名
	// 现在可能有错误的类型。
	// 而不是试图追踪并使其无效，
	// 强制设置字段不能调用一次
	// t的宽度已经计算过了。
	if t.WidthCalculated() {
		base.Fatalf("SetFields of %v: width previously calculated", t)
	}
	t.wantEtype(TSTRUCT)
	for _, f := range fields {
		// 如果类型T包含带go的字段F:notinheap
		// 类型，则T也必须是go:notinheap。否则
		// 你可以堆分配T，然后得到一个指针F，
		// 这将是一个指向go:notinheap的堆指针
		// 类型
		if f.Type != nil && f.Type.NotInHeap() {
			t.SetNotInHeap(true)
			break
		}
	}
	t.Fields().Set(fields)
}

// SetInterface设置接口类型t的基本方法。
func (t *Type) SetInterface(methods []*Field) {
	t.wantEtype(TINTER)
	t.Methods().Set(methods)
}

func (t *Type) WidthCalculated() bool {
	return t.Align > 0
}

// ArgWidth返回函数的总对齐参数大小。
// 它包括接收器、参数和结果。
func (t *Type) ArgWidth() int64 {
	t.wantEtype(TFUNC)
	return t.Extra.(*Func).Argwid
}

func (t *Type) Size() int64 {
	if t.kind == TSSA {
		if t == TypeInt128 {
			return 16
		}
		return 0
	}
	CalcSize(t)
	return t.Width
}

func (t *Type) Alignment() int64 {
	CalcSize(t)
	return int64(t.Align)
}

func (t *Type) SimpleString() string {
	return t.kind.String()
}

// Cmp是值a和b之间的比较。
// -1如果a<b
// 如果a==b，则为0
// 1如果a>b
type Cmp int8

const (
	CMPlt = Cmp(-1)
	CMPeq = Cmp(0)
	CMPgt = Cmp(1)
)

// 比较用于SSA备份的类型
// 结束，返回Cmp（CMPlt、CMPeq、CMPgt之一）。
// 对于优化器来说，答案是正确的
// 或代码生成器，但不一定是类型检查。
// 选择的顺序是任意的，只有一致性和划分
// 等价类（比较CMPeq的类型）的问题。
func (t *Type) Compare(x *Type) Cmp {
	if x == t {
		return CMPeq
	}
	return t.cmp(x)
}

func cmpForNe(x bool) Cmp {
	if x {
		return CMPlt
	}
	return CMPgt
}

func (r *Sym) cmpsym(s *Sym) Cmp {
	if r == s {
		return CMPeq
	}
	if r == nil {
		return CMPlt
	}
	if s == nil {
		return CMPgt
	}
	// 快速排序，不是很好的排序
	if len(r.Name) != len(s.Name) {
		return cmpForNe(len(r.Name) < len(s.Name))
	}
	if r.Pkg != s.Pkg {
		if len(r.Pkg.Prefix) != len(s.Pkg.Prefix) {
			return cmpForNe(len(r.Pkg.Prefix) < len(s.Pkg.Prefix))
		}
		if r.Pkg.Prefix != s.Pkg.Prefix {
			return cmpForNe(r.Pkg.Prefix < s.Pkg.Prefix)
		}
	}
	if r.Name != s.Name {
		return cmpForNe(r.Name < s.Name)
	}
	return CMPeq
}

// cmp比较两个*类型t和x，返回CMPlt，
// CMPeq，CMPgt为t<x，t==x，t>x，对于任意
// 以及以优化器为中心的比较概念。
// TODO（josharian）：确保递归接口类型的安全性
// 并用于符号列表排序。见第19869期。
func (t *Type) cmp(x *Type) Cmp {
	// 这遵循identity.go中相同的函数结构
	// 除了两个例外。
	// 1.由于需要<、=、>结果，因此会更仔细地比较符号。
	// 2.映射经过特殊处理以避免无休止的递归——映射
	// 包含Go源代码中无法表达的内部数据类型。
	if t == x {
		return CMPeq
	}
	if t == nil {
		return CMPlt
	}
	if x == nil {
		return CMPgt
	}

	if t.kind != x.kind {
		return cmpForNe(t.kind < x.kind)
	}

	if t.sym != nil || x.sym != nil {
		// 特殊情况：我们将字节和uint8分开
		// 查找错误消息。平等对待他们。
		switch t.kind {
		case TUINT8:
			if (t == Types[TUINT8] || t == ByteType) && (x == Types[TUINT8] || x == ByteType) {
				return CMPeq
			}

		case TINT32:
			if (t == Types[RuneType.kind] || t == RuneType) && (x == Types[RuneType.kind] || x == RuneType) {
				return CMPeq
			}
		}
	}

	if c := t.sym.cmpsym(x.sym); c != CMPeq {
		return c
	}

	if x.sym != nil {
		// Syms非零，如果vargens匹配，则等于。
		if t.Vargen != x.Vargen {
			return cmpForNe(t.Vargen < x.Vargen)
		}
		return CMPeq
	}
	// 两个符号都为零，请看下面的结构。

	switch t.kind {
	case TBOOL, TFLOAT32, TFLOAT64, TCOMPLEX64, TCOMPLEX128, TUNSAFEPTR, TUINTPTR,
		TINT8, TINT16, TINT32, TINT64, TINT, TUINT8, TUINT16, TUINT32, TUINT64, TUINT:
		return CMPeq

	case TSSA:
		tname := t.Extra.(string)
		xname := x.Extra.(string)
		// 渴望快速排序，而不是漂亮的排序。
		if len(tname) == len(xname) {
			if tname == xname {
				return CMPeq
			}
			if tname < xname {
				return CMPlt
			}
			return CMPgt
		}
		if len(tname) > len(xname) {
			return CMPgt
		}
		return CMPlt

	case TTUPLE:
		xtup := x.Extra.(*Tuple)
		ttup := t.Extra.(*Tuple)
		if c := ttup.first.Compare(xtup.first); c != CMPeq {
			return c
		}
		return ttup.second.Compare(xtup.second)

	case TRESULTS:
		xResults := x.Extra.(*Results)
		tResults := t.Extra.(*Results)
		xl, tl := len(xResults.Types), len(tResults.Types)
		if tl != xl {
			if tl < xl {
				return CMPlt
			}
			return CMPgt
		}
		for i := 0; i < tl; i++ {
			if c := tResults.Types[i].Compare(xResults.Types[i]); c != CMPeq {
				return c
			}
		}
		return CMPeq

	case TMAP:
		if c := t.Key().cmp(x.Key()); c != CMPeq {
			return c
		}
		return t.Elem().cmp(x.Elem())

	case TPTR, TSLICE:
		// 对于这些，没有特殊情况，它们是被处理的
		// 按开关后的通用代码。

	case TSTRUCT:
		if t.StructType().Map == nil {
			if x.StructType().Map != nil {
				return CMPlt // 零<非零
			}
			// 到最后关头
		} else if x.StructType().Map == nil {
			return CMPgt // 零>非零
		} else if t.StructType().Map.MapType().Bucket == t {
			// 两者都有非零映射
			// 包含递归类型的映射的特例，其中递归不会被命名类型破坏
			if x.StructType().Map.MapType().Bucket != x {
				return CMPlt // 水桶图是最简单的
			}
			return t.StructType().Map.cmp(x.StructType().Map)
		} else if x.StructType().Map.MapType().Bucket == x {
			return CMPgt // 水桶图是最简单的
		} // 如果t！=t、 地图。水桶，翻到一般情况

		tfs := t.FieldSlice()
		xfs := x.FieldSlice()
		for i := 0; i < len(tfs) && i < len(xfs); i++ {
			t1, x1 := tfs[i], xfs[i]
			if t1.Embedded != x1.Embedded {
				return cmpForNe(t1.Embedded < x1.Embedded)
			}
			if t1.Note != x1.Note {
				return cmpForNe(t1.Note < x1.Note)
			}
			if c := t1.Sym.cmpsym(x1.Sym); c != CMPeq {
				return c
			}
			if c := t1.Type.cmp(x1.Type); c != CMPeq {
				return c
			}
		}
		if len(tfs) != len(xfs) {
			return cmpForNe(len(tfs) < len(xfs))
		}
		return CMPeq

	case TINTER:
		tfs := t.AllMethods().Slice()
		xfs := x.AllMethods().Slice()
		for i := 0; i < len(tfs) && i < len(xfs); i++ {
			t1, x1 := tfs[i], xfs[i]
			if c := t1.Sym.cmpsym(x1.Sym); c != CMPeq {
				return c
			}
			if c := t1.Type.cmp(x1.Type); c != CMPeq {
				return c
			}
		}
		if len(tfs) != len(xfs) {
			return cmpForNe(len(tfs) < len(xfs))
		}
		return CMPeq

	case TFUNC:
		for _, f := range RecvsParamsResults {
			// 循环结构中的字段，忽略参数名称。
			tfs := f(t).FieldSlice()
			xfs := f(x).FieldSlice()
			for i := 0; i < len(tfs) && i < len(xfs); i++ {
				ta := tfs[i]
				tb := xfs[i]
				if ta.IsDDD() != tb.IsDDD() {
					return cmpForNe(!ta.IsDDD())
				}
				if c := ta.Type.cmp(tb.Type); c != CMPeq {
					return c
				}
			}
			if len(tfs) != len(xfs) {
				return cmpForNe(len(tfs) < len(xfs))
			}
		}
		return CMPeq

	case TARRAY:
		if t.NumElem() != x.NumElem() {
			return cmpForNe(t.NumElem() < x.NumElem())
		}

	case TCHAN:
		if t.ChanDir() != x.ChanDir() {
			return cmpForNe(t.ChanDir() < x.ChanDir())
		}

	default:
		e := fmt.Sprintf("Do not know how to compare %v with %v", t, x)
		panic(e)
	}

	// TARRAY、TCHAN、TPTR和TSLICE的常见元素类型比较。
	return t.Elem().cmp(x.Elem())
}

// IsKind报告t是否为指定种类的类型。
func (t *Type) IsKind(et Kind) bool {
	return t != nil && t.kind == et
}

func (t *Type) IsBoolean() bool {
	return t.kind == TBOOL
}

var unsignedEType = [...]Kind{
	TINT8:    TUINT8,
	TUINT8:   TUINT8,
	TINT16:   TUINT16,
	TUINT16:  TUINT16,
	TINT32:   TUINT32,
	TUINT32:  TUINT32,
	TINT64:   TUINT64,
	TUINT64:  TUINT64,
	TINT:     TUINT,
	TUINT:    TUINT,
	TUINTPTR: TUINTPTR,
}

// ToUnsigned返回整数类型t的无符号等效项。
func (t *Type) ToUnsigned() *Type {
	if !t.IsInteger() {
		base.Fatalf("unsignedType(%v)", t)
	}
	return Types[unsignedEType[t.kind]]
}

func (t *Type) IsInteger() bool {
	switch t.kind {
	case TINT8, TUINT8, TINT16, TUINT16, TINT32, TUINT32, TINT64, TUINT64, TINT, TUINT, TUINTPTR:
		return true
	}
	return t == UntypedInt || t == UntypedRune
}

func (t *Type) IsSigned() bool {
	switch t.kind {
	case TINT8, TINT16, TINT32, TINT64, TINT:
		return true
	}
	return false
}

func (t *Type) IsUnsigned() bool {
	switch t.kind {
	case TUINT8, TUINT16, TUINT32, TUINT64, TUINT, TUINTPTR:
		return true
	}
	return false
}

func (t *Type) IsFloat() bool {
	return t.kind == TFLOAT32 || t.kind == TFLOAT64 || t == UntypedFloat
}

func (t *Type) IsComplex() bool {
	return t.kind == TCOMPLEX64 || t.kind == TCOMPLEX128 || t == UntypedComplex
}

// IsPtr报告t是否为常规Go指针类型。
// 这不包括不安全的.Pointer。
func (t *Type) IsPtr() bool {
	return t.kind == TPTR
}

// IsPtrElem报告t是否是指针（指向t）的元素。
func (t *Type) IsPtrElem() bool {
	return t.cache.ptr != nil
}

// IsUnsafePtr报告t是否为不安全指针。
func (t *Type) IsUnsafePtr() bool {
	return t.kind == TUNSAFEPTR
}

// IsUintptr报告t是否为uintptr。
func (t *Type) IsUintptr() bool {
	return t.kind == TUINTPTR
}

// IsPtrShaped报告t是否由单个计算机指针表示。
// 除了常规的Go指针类型外，还包括贴图、通道和
// 函数类型和不安全的.Pointer。它不包括数组或结构类型
// 由单个指针形状的类型组成。
// 托多（mdempsky）：应该吗？见golang.org/issue/15028。
func (t *Type) IsPtrShaped() bool {
	return t.kind == TPTR || t.kind == TUNSAFEPTR ||
		t.kind == TMAP || t.kind == TCHAN || t.kind == TFUNC
}

// HasNil报告由t确定的值集是否包括nil。
func (t *Type) HasNil() bool {
	switch t.kind {
	case TCHAN, TFUNC, TINTER, TMAP, TNIL, TPTR, TSLICE, TUNSAFEPTR:
		return true
	}
	return false
}

func (t *Type) IsString() bool {
	return t.kind == TSTRING
}

func (t *Type) IsMap() bool {
	return t.kind == TMAP
}

func (t *Type) IsChan() bool {
	return t.kind == TCHAN
}

func (t *Type) IsSlice() bool {
	return t.kind == TSLICE
}

func (t *Type) IsArray() bool {
	return t.kind == TARRAY
}

func (t *Type) IsStruct() bool {
	return t.kind == TSTRUCT
}

func (t *Type) IsInterface() bool {
	return t.kind == TINTER
}

// IsEmptyInterface报告t是否为空接口类型。
func (t *Type) IsEmptyInterface() bool {
	return t.IsInterface() && t.AllMethods().Len() == 0
}

// IsScalar报告“t”是否为标量Go类型，例如。
// bool/int/float/complex。请注意，结构和数组类型由
// 同样，单个标量元素的属性也不被视为标量
// 指针类型也不被视为标量。
func (t *Type) IsScalar() bool {
	switch t.kind {
	case TBOOL, TINT8, TUINT8, TINT16, TUINT16, TINT32,
		TUINT32, TINT64, TUINT64, TINT, TUINT,
		TUINTPTR, TCOMPLEX64, TCOMPLEX128, TFLOAT32, TFLOAT64:
		return true
	}
	return false
}

func (t *Type) PtrTo() *Type {
	return NewPtr(t)
}

func (t *Type) NumFields() int {
	if t.kind == TRESULTS {
		return len(t.Extra.(*Results).Types)
	}
	return t.Fields().Len()
}
func (t *Type) FieldType(i int) *Type {
	if t.kind == TTUPLE {
		switch i {
		case 0:
			return t.Extra.(*Tuple).first
		case 1:
			return t.Extra.(*Tuple).second
		default:
			panic("bad tuple index")
		}
	}
	if t.kind == TRESULTS {
		return t.Extra.(*Results).Types[i]
	}
	return t.Field(i).Type
}
func (t *Type) FieldOff(i int) int64 {
	return t.Field(i).Offset
}
func (t *Type) FieldName(i int) string {
	return t.Field(i).Sym.Name
}

func (t *Type) NumElem() int64 {
	t.wantEtype(TARRAY)
	return t.Extra.(*Array).Bound
}

type componentsIncludeBlankFields bool

const (
	IgnoreBlankFields componentsIncludeBlankFields = false
	CountBlankFields  componentsIncludeBlankFields = true
)

// NumComponents返回组成t的基本元素的数量。
// 结构和数组类型被展平以进行计数。
// 所有其他类型（包括字符串、切片和接口类型）都算作一个元素。
// 如果countBlank为IgnoreBlankFields，则为blank struct fields
// （及其组成元素）不包括在计数中。
// 结构{x，y[3]int}有六个组件；[10] 结构{x，y string}有二十个。
func (t *Type) NumComponents(countBlank componentsIncludeBlankFields) int64 {
	switch t.kind {
	case TSTRUCT:
		if t.IsFuncArgStruct() {
			base.Fatalf("NumComponents func arg struct")
		}
		var n int64
		for _, f := range t.FieldSlice() {
			if countBlank == IgnoreBlankFields && f.Sym.IsBlank() {
				continue
			}
			n += f.Type.NumComponents(countBlank)
		}
		return n
	case TARRAY:
		return t.NumElem() * t.Elem().NumComponents(countBlank)
	}
	return 1
}

// SoleComponent返回t中唯一的基元组件，
// 如果确实有一个。否则，它返回nil。
// 组件按NumComponents计算，包括空白字段。
func (t *Type) SoleComponent() *Type {
	switch t.kind {
	case TSTRUCT:
		if t.IsFuncArgStruct() {
			base.Fatalf("SoleComponent func arg struct")
		}
		if t.NumFields() != 1 {
			return nil
		}
		return t.Field(0).Type.SoleComponent()
	case TARRAY:
		if t.NumElem() != 1 {
			return nil
		}
		return t.Elem().SoleComponent()
	}
	return t
}

// ChanDir返回通道类型t的方向。
// 方向将为Crecv、Csend或Cboth之一。
func (t *Type) ChanDir() ChanDir {
	t.wantEtype(TCHAN)
	return t.Extra.(*Chan).Dir
}

func (t *Type) IsMemory() bool {
	if t == TypeMem || t.kind == TTUPLE && t.Extra.(*Tuple).second == TypeMem {
		return true
	}
	if t.kind == TRESULTS {
		if types := t.Extra.(*Results).Types; len(types) > 0 && types[len(types)-1] == TypeMem {
			return true
		}
	}
	return false
}
func (t *Type) IsFlags() bool   { return t == TypeFlags }
func (t *Type) IsVoid() bool    { return t == TypeVoid }
func (t *Type) IsTuple() bool   { return t.kind == TTUPLE }
func (t *Type) IsResults() bool { return t.kind == TRESULTS }

// IsUntyped报告t是否为非类型化类型。
func (t *Type) IsUntyped() bool {
	if t == nil {
		return false
	}
	if t == UntypedString || t == UntypedBool {
		return true
	}
	switch t.kind {
	case TNIL, TIDEAL:
		return true
	}
	return false
}

// HasPointers报告t是否包含堆指针。
// 请注意，此函数忽略要转到的指针：notinheap类型。
func (t *Type) HasPointers() bool {
	switch t.kind {
	case TINT, TUINT, TINT8, TUINT8, TINT16, TUINT16, TINT32, TUINT32, TINT64,
		TUINT64, TUINTPTR, TFLOAT32, TFLOAT64, TCOMPLEX64, TCOMPLEX128, TBOOL, TSSA:
		return false

	case TARRAY:
		if t.NumElem() == 0 { // 空数组没有指针
			return false
		}
		return t.Elem().HasPointers()

	case TSTRUCT:
		for _, t1 := range t.Fields().Slice() {
			if t1.Type.HasPointers() {
				return true
			}
		}
		return false

	case TPTR, TSLICE:
		return !t.Elem().NotInHeap()

	case TTUPLE:
		ttup := t.Extra.(*Tuple)
		return ttup.first.HasPointers() || ttup.second.HasPointers()

	case TRESULTS:
		types := t.Extra.(*Results).Types
		for _, et := range types {
			if et.HasPointers() {
				return true
			}
		}
		return false
	}

	return true
}

// 如果T是具体类型，则Tie返回“T”，
// 如果t是接口类型，则为'I'，如果t是空接口类型，则为'E'。
// 它用于生成对conv*和assert*运行时例程的调用。
func (t *Type) Tie() byte {
	if t.IsEmptyInterface() {
		return 'E'
	}
	if t.IsInterface() {
		return 'I'
	}
	return 'T'
}

var recvType *Type

// FakeRecvType返回用于接口方法接收器的单例类型。
func FakeRecvType() *Type {
	if recvType == nil {
		recvType = NewPtr(New(TSTRUCT))
	}
	return recvType
}

var (
	// TSSA类型。HasPointers假设它们是无指针的。
	TypeInvalid   = newSSA("invalid")
	TypeMem       = newSSA("mem")
	TypeFlags     = newSSA("flags")
	TypeVoid      = newSSA("void")
	TypeInt128    = newSSA("int128")
	TypeResultMem = newResults([]*Type{TypeMem})
)

// NewNamed返回给定类型名的新命名类型。obj应该是一个
// 国名。新类型不完整（标记为TFORW kind），并且基础
// 应稍后通过setUnderground（）设置类型。对该类型的引用是
// 在填充类型之前一直保持，以便在
// 字体完整。
func NewNamed(obj Object) *Type {
	t := New(TFORW)
	t.sym = obj.Sym()
	t.nod = obj
	return t
}

// Obj为命名类型t返回规范类型名称节点，为未命名类型返回nil。
func (t *Type) Obj() Object {
	if t.sym != nil {
		return t.nod
	}
	return nil
}

// 设置基础类型。SetUnderground会自动更新任何
// 正在等待此类型完成的类型。
func (t *Type) SetUnderlying(underlying *Type) {
	if underlying.kind == TFORW {
		// 这种类型尚未计算；如果是，则更新n。
		underlying.ForwardType().Copyto = append(underlying.ForwardType().Copyto, t)
		return
	}

	ft := t.ForwardType()

	// TODO（mdempsky）：修复类型重新点燃。
	t.kind = underlying.kind
	t.Extra = underlying.Extra
	t.Width = underlying.Width
	t.Align = underlying.Align
	t.underlying = underlying.underlying

	if underlying.NotInHeap() {
		t.SetNotInHeap(true)
	}
	if underlying.Broke() {
		t.SetBroke(true)
	}
	if underlying.HasTParam() {
		t.SetHasTParam(true)
	}

	// spec:“声明的类型不继承任何绑定的方法
	// 现有类型，但接口的方法集
	// 类型[…]保持不变。”
	if t.IsInterface() {
		t.methods = underlying.methods
		t.allMethods = underlying.allMethods
	}

	// 更新等待此类型的类型。
	for _, w := range ft.Copyto {
		w.SetUnderlying(t)
	}

	// 再次检查类型作为嵌入类型的使用。
	if ft.Embedlineno.IsKnown() {
		if t.IsPtr() || t.IsUnsafePtr() {
			base.ErrorfAt(ft.Embedlineno, "embedded type cannot be a pointer")
		}
	}
}

func fieldsHasTParam(fields []*Field) bool {
	for _, f := range fields {
		if f.Type != nil && f.Type.HasTParam() {
			return true
		}
	}
	return false
}

// NewBasic返回给定类型的新基本类型。
func NewBasic(kind Kind, obj Object) *Type {
	t := New(kind)
	t.sym = obj.Sym()
	t.nod = obj
	return t
}

// NewInterface为给定的方法和方法返回一个新接口
// 嵌入类型。嵌入类型指定为不带Sym的字段。
func NewInterface(pkg *Pkg, methods []*Field) *Type {
	t := New(TINTER)
	t.SetInterface(methods)
	for _, f := range methods {
		// f、 对于断开的接口声明，类型可以为nil
		if f.Type != nil && f.Type.HasTParam() {
			t.SetHasTParam(true)
			break
		}
	}
	if anyBroke(methods) {
		t.SetBroke(true)
	}
	t.Extra.(*Interface).pkg = pkg
	return t
}

// NewTypeParam返回一个新的类型参数。
func NewTypeParam(pkg *Pkg) *Type {
	t := New(TTYPEPARAM)
	t.Extra.(*Interface).pkg = pkg
	t.SetHasTParam(true)
	return t
}

const BOGUS_FUNARG_OFFSET = -1000000000

func unzeroFieldOffsets(f []*Field) {
	for i := range f {
		f[i].Offset = BOGUS_FUNARG_OFFSET // 如果不纠正，将导致爆炸
	}
}

// NewSignature为给定的接收者返回一个新的函数类型，
// 参数、结果和类型参数，其中任何参数都可以为零。
func NewSignature(pkg *Pkg, recv *Field, tparams, params, results []*Field) *Type {
	var recvs []*Field
	if recv != nil {
		recvs = []*Field{recv}
	}

	t := New(TFUNC)
	ft := t.FuncType()

	funargs := func(fields []*Field, funarg Funarg) *Type {
		s := NewStruct(NoPkg, fields)
		s.StructType().Funarg = funarg
		if s.Broke() {
			t.SetBroke(true)
		}
		return s
	}

	if recv != nil {
		recv.Offset = BOGUS_FUNARG_OFFSET
	}
	unzeroFieldOffsets(params)
	unzeroFieldOffsets(results)
	ft.Receiver = funargs(recvs, FunargRcvr)
	// TODO（danscales）：如果没有Tparam，只需在此处使用nil（节省内存）
	ft.TParams = funargs(tparams, FunargTparams)
	ft.Params = funargs(params, FunargParams)
	ft.Results = funargs(results, FunargResults)
	ft.pkg = pkg
	if len(tparams) > 0 || fieldsHasTParam(recvs) || fieldsHasTParam(params) ||
		fieldsHasTParam(results) {
		t.SetHasTParam(true)
	}

	return t
}

// NewStruct返回具有给定字段的新结构。
func NewStruct(pkg *Pkg, fields []*Field) *Type {
	t := New(TSTRUCT)
	t.SetFields(fields)
	if anyBroke(fields) {
		t.SetBroke(true)
	}
	t.Extra.(*Struct).pkg = pkg
	if fieldsHasTParam(fields) {
		t.SetHasTParam(true)
	}
	return t
}

func anyBroke(fields []*Field) bool {
	for _, f := range fields {
		if f.Broke() {
			return true
		}
	}
	return false
}

var (
	IsInt     [NTYPE]bool
	IsFloat   [NTYPE]bool
	IsComplex [NTYPE]bool
	IsSimple  [NTYPE]bool
)

var IsOrdered [NTYPE]bool

// IsReflexive报告t是否具有自反相等运算符。
// 也就是说，如果对于类型为t的所有x，x==x。
func IsReflexive(t *Type) bool {
	switch t.Kind() {
	case TBOOL,
		TINT,
		TUINT,
		TINT8,
		TUINT8,
		TINT16,
		TUINT16,
		TINT32,
		TUINT32,
		TINT64,
		TUINT64,
		TUINTPTR,
		TPTR,
		TUNSAFEPTR,
		TSTRING,
		TCHAN:
		return true

	case TFLOAT32,
		TFLOAT64,
		TCOMPLEX64,
		TCOMPLEX128,
		TINTER:
		return false

	case TARRAY:
		return IsReflexive(t.Elem())

	case TSTRUCT:
		for _, t1 := range t.Fields().Slice() {
			if !IsReflexive(t1.Type) {
				return false
			}
		}
		return true

	default:
		base.Fatalf("bad type for map key: %v", t)
		return false
	}
}

// 这种类型可以直接存储在接口字中吗？
// 是，如果表示为单指针。
func IsDirectIface(t *Type) bool {
	if t.Broke() {
		return false
	}

	switch t.Kind() {
	case TPTR:
		// 指向notinheap类型的指针必须间接存储。见第42076期。
		return !t.Elem().NotInHeap()
	case TCHAN,
		TMAP,
		TFUNC,
		TUNSAFEPTR:
		return true

	case TARRAY:
		// 1直接iface类型的数组可以是直接数组。
		return t.NumElem() == 1 && IsDirectIface(t.Elem())

	case TSTRUCT:
		// 具有1个direct iface类型字段的结构可以是direct。
		return t.NumFields() == 1 && IsDirectIface(t.Field(0).Type)
	}

	return false
}

// IsInterfaceMethod报告（字段）m是否为
// 接口方法。这种方法有其独特的优点
// 特殊接收器类型。FakeRecvType（）。
func IsInterfaceMethod(f *Type) bool {
	return f.Recv().Type == FakeRecvType()
}

// IsMethodApplicable报告是否可以在
// 类型t的值。这是必要的，因为我们计算单个
// 方法集，但某些*T方法不是
// 适用于T型接收机。
func IsMethodApplicable(t *Type, m *Field) bool {
	return t.IsPtr() || !m.Type.Recv().Type.IsPtr() || IsInterfaceMethod(m.Type) || m.Embedded == 2
}

// IsRuntimePkg报告p是否为包运行时。
func IsRuntimePkg(p *Pkg) bool {
	if base.Flag.CompilingRuntime && p == LocalPkg {
		return true
	}
	return p.Path == "runtime"
}

// IsReflectPkg报告p是否为包反射。
func IsReflectPkg(p *Pkg) bool {
	if p == LocalPkg {
		return base.Ctxt.Pkgpath == "reflect"
	}
	return p.Path == "reflect"
}

// ReceiverBaseType返回基础类型（如果有），
// 它拥有具有接收器参数t的方法。
// 结果是命名类型或匿名结构。
func ReceiverBaseType(t *Type) *Type {
	if t == nil {
		return nil
	}

	// 如果指针在那里，就把它剥掉。
	if t.IsPtr() {
		if t.Sym() != nil {
			return nil
		}
		t = t.Elem()
		if t == nil {
			return nil
		}
	}

	// 必须是命名类型或匿名结构。
	if t.Sym() == nil && !t.IsStruct() {
		return nil
	}

	// 检查类型。
	if IsSimple[t.Kind()] {
		return t
	}
	switch t.Kind() {
	case TARRAY, TCHAN, TFUNC, TMAP, TSLICE, TSTRING, TSTRUCT:
		return t
	}
	return nil
}

func FloatForComplex(t *Type) *Type {
	switch t.Kind() {
	case TCOMPLEX64:
		return Types[TFLOAT32]
	case TCOMPLEX128:
		return Types[TFLOAT64]
	}
	base.Fatalf("unexpected type: %v", t)
	return nil
}

func ComplexForFloat(t *Type) *Type {
	switch t.Kind() {
	case TFLOAT32:
		return Types[TCOMPLEX64]
	case TFLOAT64:
		return Types[TCOMPLEX128]
	}
	base.Fatalf("unexpected type: %v", t)
	return nil
}

func TypeSym(t *Type) *Sym {
	return TypeSymLookup(TypeSymName(t))
}

func TypeSymLookup(name string) *Sym {
	typepkgmu.Lock()
	s := typepkg.Lookup(name)
	typepkgmu.Unlock()
	return s
}

func TypeSymName(t *Type) string {
	name := t.ShortString()
	// 为#17752的Noalg类型使用单独的符号名称。
	if TypeHasNoAlg(t) {
		name = "noalg." + name
	}
	return name
}

// 运行时类型信息的假包（标题）
// 不要直接访问，请使用下面的typeLookup。
var (
	typepkgmu sync.Mutex // 保护typepkg查找
	typepkg   = NewPkg("type", "type")
)

var SimType [NTYPE]Kind
